package service

import (
	"fmt"
	"mime/multipart"
	"strconv"
	"strings"
	"trpg-base/entity"
	"trpg-common/constants"
	common_dto "trpg-common/dto"
	"trpg-common/logger"
	"trpg-common/utils/gorm_util"
	"trpg-common/utils/json_util"
	"trpg-common/utils/oss_util"
	"trpg-common/utils/time_util"
	"unicode"

	"github.com/pkg/errors"
)

type CharacterService struct{}

func (c CharacterService) InsertOrUpdateCharacter(character entity.Character, user common_dto.UserInfo) entity.Character {
	if character.Id == 0 {
		character.Creator = user.Uid
		character.Modifier = user.Uid
		character.GmtCreated = time_util.Now()
		character.GmtModified = time_util.Now()
		// 校验是否已经存在同一用户下同name的角色
		repeat := make([]entity.Character, 0)
		gorm_util.SelectByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.Character{}).Eq("uid", user.Uid).Eq("name", character.Name).Eq("is_deleted", constants.DeleteNo), &repeat)
		if len(repeat) != 0 {
			logger.Logger.Panicf("%+v", errors.New("存在同名的角色，请修改唯一名"))
		}
		character.Uid = user.Uid
		vars := c.dealWithRememberedVars(character.RememberedVarsStr)
		character.RememberedVars = string(json_util.Marshal(&vars))
		gorm_util.InsertUpdateOne(&character)
	} else {
		character.Modifier = user.Uid
		character.GmtModified = time_util.Now()
		// 校验是否已经存在同一用户下同name的角色
		repeat := make([]entity.Character, 0)
		gorm_util.SelectByParamBuilder(gorm_util.NewParamBuilder().Model(&entity.Character{}).Eq("uid", user.Uid).Eq("name", character.Name).Eq("is_deleted", constants.DeleteNo), &repeat)
		if len(repeat) != 0 && repeat[0].Id != character.Id {
			logger.Logger.Panicf("%+v", errors.New("存在同名的角色，请修改唯一名"))
		}
		character.Uid = user.Uid
		vars := c.dealWithRememberedVars(character.RememberedVarsStr)
		character.RememberedVars = string(json_util.Marshal(&vars))
		gorm_util.UpdateOneByCondition(&character)
	}
	return character
}

func (c CharacterService) dealWithRememberedVars(str string) map[string]int64 {
	str = strings.ReplaceAll(str, ".st", "")
	str = strings.TrimSpace(str)
	key := ""
	valStr := ""
	keySlice := make([]string, 0)
	valSlice := make([]int64, 0)
	for _, char := range str {
		if unicode.IsDigit(char) {
			if key != "" {
				keySlice = append(keySlice, key)
				key = ""
			}
			valStr += fmt.Sprintf("%c", char)
		} else {
			if valStr != "" {
				val, _ := strconv.ParseInt(valStr, 10, 64)
				valSlice = append(valSlice, val)
				valStr = ""
			}
			key += fmt.Sprintf("%c", char)
		}
	}
	if valStr != "" {
		val, _ := strconv.ParseInt(valStr, 10, 64)
		valSlice = append(valSlice, val)
	}
	res := make(map[string]int64)
	for i, _ := range keySlice {
		res[keySlice[i]] = valSlice[i]
	}
	return res
}

func (c CharacterService) UploadExcel(file *multipart.FileHeader, user common_dto.UserInfo, id int64) {
	suffix := "xlsx"
	excelPath := "/character/" + user.Uid + "/" + strconv.FormatInt(id, 10) + "." + suffix
	oss_util.UploadMultiFile(file, excelPath)
	character := entity.Character{}
	character.Id = id
	character.ExcelPath = excelPath
	character.Modifier = user.Uid
	character.GmtModified = time_util.Now()
	// 修改库
	gorm_util.UpdateOneByCondition(&character)
}

func (c CharacterService) GetCharacters(user common_dto.UserInfo) []entity.Character {
	res := make([]entity.Character, 0)
	paramBuilder := gorm_util.NewParamBuilder().Model(&entity.Character{}).Select("id, name").Eq("uid", user.Uid).Eq("is_deleted", constants.DeleteNo)
	gorm_util.SelectByParamBuilder(paramBuilder, &res)
	return res
}

func (c CharacterService) GetCharacterEnum(user common_dto.UserInfo) []common_dto.CodeEnumDTO {
	characters := make([]entity.Character, 0)
	paramBuilder := gorm_util.NewParamBuilder().Model(&entity.Character{}).Select("id, name").Eq("uid", user.Uid).Eq("is_deleted", constants.DeleteNo)
	gorm_util.SelectByParamBuilder(paramBuilder, &characters)
	res := make([]common_dto.CodeEnumDTO, 0, len(characters))
	for _, ch := range characters {
		res = append(res, common_dto.CodeEnumDTO{
			Label:    ch.Name,
			Value:    ch.Id,
			Disabled: false,
		})
	}
	return res
}

func (c CharacterService) GetCharacterDetail(id int64) entity.Character {
	res := entity.Character{}
	res.Id = id
	res.IsDeleted = constants.DeleteNo
	gorm_util.SelectOneByCondition(&res)
	if res.ExcelPath != "" {
		url := oss_util.GetUniqueUrlByKey(res.ExcelPath)
		res.ExcelUrl = url
	}
	return res
}
